#ifndef FIXPOINT_TABLES_H_INCLUDED
#define FIXPOINT_TABLES_H_INCLUDED

/*
* Copyright (c) 2010 Michael Collins
*
* This file is part of TerraFirma.
*
* TerraFirma is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* TerraFirma is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with TerraFirma.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdint.h>

namespace fixedpoint
{
    //Sine lookup values normalized between 0 and 1 for normalized ranges between 0 an pi/2
    //The upper half-word is implied to be 0
    static const uint16_t sin_lu [256] =
    {
        0x0000,
        0x0192,
        0x0324,
        0x04b6,
        0x0648,
        0x07da,
        0x096c,
        0x0afe,
        0x0c8f,
        0x0e21,
        0x0fb2,
        0x1144,
        0x12d5,
        0x1466,
        0x15f6,
        0x1787,
        0x1917,
        0x1aa7,
        0x1c37,
        0x1dc7,
        0x1f56,
        0x20e5,
        0x2273,
        0x2402,
        0x2590,
        0x271d,
        0x28aa,
        0x2a37,
        0x2bc4,
        0x2d50,
        0x2edb,
        0x3066,
        0x31f1,
        0x337b,
        0x3505,
        0x368e,
        0x3817,
        0x399f,
        0x3b26,
        0x3cad,
        0x3e33,
        0x3fb9,
        0x413e,
        0x42c3,
        0x4447,
        0x45ca,
        0x474d,
        0x48ce,
        0x4a50,
        0x4bd0,
        0x4d50,
        0x4ecf,
        0x504d,
        0x51ca,
        0x5347,
        0x54c3,
        0x563e,
        0x57b8,
        0x5931,
        0x5aaa,
        0x5c22,
        0x5d98,
        0x5f0e,
        0x6083,
        0x61f7,
        0x636a,
        0x64dc,
        0x664d,
        0x67bd,
        0x692d,
        0x6a9b,
        0x6c08,
        0x6d74,
        0x6edf,
        0x7049,
        0x71b1,
        0x7319,
        0x7480,
        0x75e5,
        0x774a,
        0x78ad,
        0x7a0f,
        0x7b70,
        0x7cd0,
        0x7e2e,
        0x7f8b,
        0x80e7,
        0x8242,
        0x839c,
        0x84f4,
        0x864b,
        0x87a1,
        0x88f5,
        0x8a48,
        0x8b9a,
        0x8cea,
        0x8e39,
        0x8f87,
        0x90d3,
        0x921e,
        0x9368,
        0x94b0,
        0x95f6,
        0x973c,
        0x987f,
        0x99c2,
        0x9b02,
        0x9c42,
        0x9d7f,
        0x9ebc,
        0x9ff6,
        0xa12f,
        0xa267,
        0xa39d,
        0xa4d2,
        0xa605,
        0xa736,
        0xa866,
        0xa994,
        0xaac0,
        0xabeb,
        0xad14,
        0xae3b,
        0xaf61,
        0xb085,
        0xb1a8,
        0xb2c8,
        0xb3e7,
        0xb504,
        0xb620,
        0xb73a,
        0xb852,
        0xb968,
        0xba7c,
        0xbb8f,
        0xbca0,
        0xbdae,
        0xbebc,
        0xbfc7,
        0xc0d0,
        0xc1d8,
        0xc2de,
        0xc3e2,
        0xc4e3,
        0xc5e4,
        0xc6e2,
        0xc7de,
        0xc8d8,
        0xc9d1,
        0xcac7,
        0xcbbb,
        0xccae,
        0xcd9f,
        0xce8d,
        0xcf7a,
        0xd064,
        0xd14d,
        0xd233,
        0xd318,
        0xd3fa,
        0xd4db,
        0xd5b9,
        0xd695,
        0xd770,
        0xd848,
        0xd91e,
        0xd9f2,
        0xdac4,
        0xdb94,
        0xdc61,
        0xdd2d,
        0xddf6,
        0xdebe,
        0xdf83,
        0xe046,
        0xe106,
        0xe1c5,
        0xe282,
        0xe33c,
        0xe3f4,
        0xe4aa,
        0xe55e,
        0xe60f,
        0xe6be,
        0xe76b,
        0xe816,
        0xe8bf,
        0xe965,
        0xea09,
        0xeaab,
        0xeb4b,
        0xebe8,
        0xec83,
        0xed1c,
        0xedb2,
        0xee46,
        0xeed8,
        0xef68,
        0xeff5,
        0xf080,
        0xf109,
        0xf18f,
        0xf213,
        0xf294,
        0xf314,
        0xf391,
        0xf40b,
        0xf484,
        0xf4fa,
        0xf56d,
        0xf5de,
        0xf64d,
        0xf6ba,
        0xf724,
        0xf78b,
        0xf7f1,
        0xf853,
        0xf8b4,
        0xf912,
        0xf96e,
        0xf9c7,
        0xfa1e,
        0xfa73,
        0xfac5,
        0xfb14,
        0xfb61,
        0xfbac,
        0xfbf5,
        0xfc3b,
        0xfc7e,
        0xfcbf,
        0xfcfe,
        0xfd3a,
        0xfd74,
        0xfdab,
        0xfde0,
        0xfe13,
        0xfe43,
        0xfe70,
        0xfe9b,
        0xfec4,
        0xfeea,
        0xff0e,
        0xff2f,
        0xff4e,
        0xff6a,
        0xff84,
        0xff9c,
        0xffb1,
        0xffc3,
        0xffd3,
        0xffe1,
        0xffec,
        0xfff4,
        0xfffb,
        0xfffe
    };

    //Arcsine lookup values normalized between 0 and pi/2 for ranges normalized between 0 and 1
    static const uint16_t asin_lu [256] =
    {
        0x0000,
        0x00a2,
        0x0145,
        0x01e8,
        0x028b,
        0x032e,
        0x03d1,
        0x0474,
        0x0518,
        0x05bb,
        0x065e,
        0x0701,
        0x07a4,
        0x0847,
        0x08ea,
        0x098e,
        0x0a31,
        0x0ad4,
        0x0b77,
        0x0c1b,
        0x0cbe,
        0x0d62,
        0x0e05,
        0x0ea9,
        0x0f4d,
        0x0ff0,
        0x1094,
        0x1138,
        0x11dc,
        0x1280,
        0x1324,
        0x13c8,
        0x146c,
        0x1511,
        0x15b5,
        0x165a,
        0x16fe,
        0x17a3,
        0x1848,
        0x18ec,
        0x1991,
        0x1a36,
        0x1adc,
        0x1b81,
        0x1c26,
        0x1ccc,
        0x1d71,
        0x1e17,
        0x1ebd,
        0x1f63,
        0x2009,
        0x20af,
        0x2156,
        0x21fc,
        0x22a3,
        0x234a,
        0x23f0,
        0x2498,
        0x253f,
        0x25e6,
        0x268e,
        0x2736,
        0x27dd,
        0x2885,
        0x292e,
        0x29d6,
        0x2a7f,
        0x2b27,
        0x2bd0,
        0x2c7a,
        0x2d23,
        0x2dcc,
        0x2e76,
        0x2f20,
        0x2fca,
        0x3075,
        0x311f,
        0x31ca,
        0x3275,
        0x3320,
        0x33cc,
        0x3477,
        0x3523,
        0x35cf,
        0x367c,
        0x3728,
        0x37d5,
        0x3882,
        0x3930,
        0x39de,
        0x3a8c,
        0x3b3a,
        0x3be8,
        0x3c97,
        0x3d46,
        0x3df5,
        0x3ea5,
        0x3f55,
        0x4005,
        0x40b6,
        0x4167,
        0x4218,
        0x42ca,
        0x437b,
        0x442e,
        0x44e0,
        0x4593,
        0x4646,
        0x46fa,
        0x47ae,
        0x4862,
        0x4917,
        0x49cc,
        0x4a81,
        0x4b37,
        0x4bed,
        0x4ca4,
        0x4d5b,
        0x4e12,
        0x4eca,
        0x4f82,
        0x503b,
        0x50f4,
        0x51ae,
        0x5268,
        0x5322,
        0x53dd,
        0x5499,
        0x5555,
        0x5611,
        0x56ce,
        0x578c,
        0x584a,
        0x5908,
        0x59c7,
        0x5a87,
        0x5b47,
        0x5c07,
        0x5cc9,
        0x5d8a,
        0x5e4d,
        0x5f10,
        0x5fd3,
        0x6097,
        0x615c,
        0x6222,
        0x62e8,
        0x63ae,
        0x6476,
        0x653e,
        0x6607,
        0x66d0,
        0x679a,
        0x6865,
        0x6931,
        0x69fd,
        0x6aca,
        0x6b98,
        0x6c67,
        0x6d37,
        0x6e07,
        0x6ed8,
        0x6faa,
        0x707d,
        0x7151,
        0x7226,
        0x72fb,
        0x73d2,
        0x74a9,
        0x7582,
        0x765b,
        0x7736,
        0x7811,
        0x78ee,
        0x79cc,
        0x7aaa,
        0x7b8a,
        0x7c6b,
        0x7d4d,
        0x7e31,
        0x7f15,
        0x7ffb,
        0x80e2,
        0x81cb,
        0x82b4,
        0x839f,
        0x848c,
        0x857a,
        0x8669,
        0x875a,
        0x884c,
        0x8940,
        0x8a36,
        0x8b2d,
        0x8c26,
        0x8d21,
        0x8e1d,
        0x8f1b,
        0x901c,
        0x911e,
        0x9222,
        0x9328,
        0x9430,
        0x953a,
        0x9647,
        0x9756,
        0x9867,
        0x997b,
        0x9a91,
        0x9baa,
        0x9cc6,
        0x9de4,
        0x9f05,
        0xa02a,
        0xa151,
        0xa27c,
        0xa3aa,
        0xa4db,
        0xa610,
        0xa749,
        0xa885,
        0xa9c6,
        0xab0b,
        0xac55,
        0xada3,
        0xaef6,
        0xb04f,
        0xb1ac,
        0xb310,
        0xb479,
        0xb5e9,
        0xb760,
        0xb8dd,
        0xba63,
        0xbbf0,
        0xbd87,
        0xbf26,
        0xc0d0,
        0xc285,
        0xc445,
        0xc613,
        0xc7ee,
        0xc9da,
        0xcbd6,
        0xcde7,
        0xd00d,
        0xd24c,
        0xd4a8,
        0xd726,
        0xd9cc,
        0xdca5,
        0xdfbc,
        0xe326,
        0xe706,
        0xeb9d,
        0xf197
    };

    //Square root raw lookup vales, index is based on integral log_2 of argument
    //static const int32_t sqrt_lu [32] = {0};

    //Inverse square root raw lookup vales, index is based on integral log_2 of argument
    static const int32_t invsqrt_lu [32] =
    {
        0x01000000,
        0x00b504f3,
        0x00800000,
        0x005a8279,
        0x00400000,
        0x002d413c,
        0x00200000,
        0x0016a09e,
        0x00100000,
        0x000b504f,
        0x00080000,
        0x0005a827,
        0x00040000,
        0x0002d413,
        0x00020000,
        0x00016a09,
        0x00010000,
        0x0000b504,
        0x00008000,
        0x00005a82,
        0x00004000,
        0x00002d41,
        0x00002000,
        0x000016a0,
        0x00001000,
        0x00000b50,
        0x00000800,
        0x000005a8,
        0x00000400,
        0x000002d4,
        0x00000200,
        0x80000000
    };

    //Linear interpolation function between 2 sample points and a weight
    inline uint32_t interpolate(uint32_t p0, uint32_t p1, uint8_t weight)
    {
        uint32_t retval = p0 * weight + p1 * (256 - weight);
        return retval / 256;
    }

    //Returns the digit place of the most significant 1 (this is the basis for integral log_2)
    inline uint8_t most_sig_1(uint32_t a)
    {
        uint8_t retval;
        if (a >= 0x00010000)
        {
            a >>= 16;
            retval = 16;
        }
        else retval = 0;
        if (a >= 0x00000100)
        {
            a >>= 8;
            retval += 8;
        }
        if (a >= 0x00000010)
        {
            a >>= 4;
            retval += 4;
        }
        if (a >= 0x00000004)
        {
            a >>= 2;
            retval += 2;
        }
        if (a >= 0x00000002)
        {
            a >>= 1;
            retval += 1;
        }
        //if(a != 0) {retval++;}
        return retval;
    }


}
#endif // FIXPOINT_TABLES_H_INCLUDED
